﻿using adb;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Linq;
using Z.EntityFramework.Plus;
using Masuit.Tools.Security;
using System.Collections.Generic;
using PowerStation.RequestModel;
using Microsoft.EntityFrameworkCore;
using adb.excel;
using System.IO;
using Masuit.Tools;
using Microsoft.Net.Http.Headers;
using System;
using PowerStation.AppCode;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;
using System.Net;
using Microsoft.AspNetCore.Authorization;

namespace PowerStation.AppCode
{
    /// <summary>
    /// 增删查改
    /// </summary>
    [Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class RankCheck : Attribute, IActionFilter
    {
        /// <summary>
        /// 数据库上下文
        /// </summary>
        protected MyDbContext _db;
        /// <summary>
        /// 
        /// </summary>
        protected LogDbContext _log;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="db"></param>
        /// <param name="logDb"></param>
        public RankCheck(MyDbContext db,LogDbContext logDb) {
            this._db = db;
            this._log = logDb;
        }





        /// <summary>
        /// 方法运行后
        /// </summary>
        /// <param name="context"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnActionExecuted(ActionExecutedContext context)
        {
            try
            {
                if (context.HttpContext.User == null) return;
                var lst = context.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
                if (lst != null && context.HttpContext.Request.Method != "GET")//关闭测试
                {
                    var str = context.HttpContext.Request.QueryString + "========";
                    if (context.HttpContext.Request.Body.Length > 0)
                    {
                        using (var reader = new StreamReader(context.HttpContext.Request.Body, System.Text.Encoding.UTF8))
                        {
                            reader.BaseStream.Seek(0, SeekOrigin.Begin);  //大概是== Request.Body.Position = 0;的意思
                            str += reader.ReadToEndAsync().Result;
                            reader.BaseStream.Seek(0, SeekOrigin.Begin);  //读完后也复原
                        }
                    }
                    if (str.Length > 2000)
                    {
                        str = str.Substring(0, 2000);
                    }
                    this._log.tLogs.Add(new tLogs()
                    {
                        logsIp = $"{context.HttpContext.Connection.RemoteIpAddress}:{context.HttpContext.Connection.RemotePort}",
                        logsMd5 = Masuit.Tools.Security.Encrypt.MDString(str),
                        logsPath = context.HttpContext.Request.Path,
                        logsPlatform = context.HttpContext.Request.Headers["User-Agent"].Contains("mobile") ? "移动端" : "PC端",
                        logsUser_userId_fk = lst.Value.ConvertTo<decimal>(),
                        logsData = str,
                        logsType = context.HttpContext.Request.Method
                    });
                    this._log.SaveChanges();
                }
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }

        }
        /// <summary>
        /// 方法运行前
        /// </summary>
        /// <param name="context"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnActionExecuting(ActionExecutingContext context)
        {

            var upCheck = true;
            var needCheck = true;
            for (int i = context.ActionDescriptor.EndpointMetadata.Count - 1; i >= 0; i--)
            {
                var item = context.ActionDescriptor.EndpointMetadata[i];
                if (upCheck && item is AttrSplit)
                {
                    upCheck = false;
                    continue;
                }
                if (item is IAllowAnonymous)
                {
                    if (upCheck)
                    {
                        needCheck = false;
                        break;
                    }
                    else
                    {
                        needCheck = false;
                    }
                }
                else if (item is IAuthorizeData)
                {
                    if (upCheck)
                    {
                        needCheck = true;
                        break;
                    }
                    else
                    {
                        needCheck = true;
                    }
                }
            }
            if (needCheck == false) return;
            var lst = context.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
            if (lst == null)
            {
                noLogin(context);
                return;
            }
            else
            {
                if (this._db.tKey.Where(x => x.keyType == 10).FromCache().Any(x =>(context.HttpContext.Request.Path + ";").Contains(x.keyValue) && x.dataState == 0) == true) {
                    return;
                }
                if (lst.Value.ConvertTo<decimal>() != 1 && (this._db.vUserPermission.Any(x => x.userId == lst.Value.ConvertTo<long>() && x.keyValue.Contains(context.HttpContext.Request.Path + ";"))) == false)
                {
                    error(context);
                    return;
                }
            }
        }
        private void error(ActionExecutingContext context) {
            ContentResult res = new ContentResult();
            res.Content = "未授权";
            res.StatusCode = (int)HttpStatusCode.Forbidden;
            context.Result = res;
        }
        private void noLogin(ActionExecutingContext context)
        {
            ContentResult res = new ContentResult();
            res.Content = "未登陆";
            res.StatusCode = (int)HttpStatusCode.Unauthorized;
            context.Result = res;
        }
    }
}
